// ===----------------------------------------------------------------------===
// 
//  Copyright (C) 2022 Sophgo Technologies Inc.  All rights reserved.
// 
//  SOPHON-DEMO is licensed under the 2-Clause BSD License except for the
//  third-party components.
// 
// ===----------------------------------------------------------------------===

#ifndef COMMON_H_
#define COMMON_H_


#include "bmcv_api.h"
#include "bmcv_api_ext.h"
#include "bmlib_runtime.h"
#include <memory>
#include <vector>
#include "opencv2/opencv.hpp"

#define MAX_BATCH 4
#define MAX_YOLO_INPUT_NUM 8
#define MAX_YOLO_ANCHOR_NUM 8
typedef struct {
  unsigned long long bottom_addr[MAX_YOLO_INPUT_NUM];
  unsigned long long top_addr;
  unsigned long long detected_num_addr;
  int input_num;
  int batch_num;
  int hw_shape[MAX_YOLO_INPUT_NUM][2];
  int num_classes;
  int num_boxes;
  int keep_top_k;
  float nms_threshold;
  float confidence_threshold;
  float bias[MAX_YOLO_INPUT_NUM * MAX_YOLO_ANCHOR_NUM * 2];
  float anchor_scale[MAX_YOLO_INPUT_NUM];
  int clip_box;
}__attribute__((packed)) tpu_kernel_api_yolov5NMS_t;

typedef struct {
  unsigned long long bottom_addr[MAX_YOLO_INPUT_NUM];
  unsigned long long top_addr;
  unsigned long long detected_num_addr;
  int input_num;
  int batch_num;
  int hw_shape[MAX_YOLO_INPUT_NUM][2];
  int num_classes;
  int num_boxes;
  int keep_top_k;
  float nms_threshold;
  float confidence_threshold;
  float bias[MAX_YOLO_INPUT_NUM * MAX_YOLO_ANCHOR_NUM * 2];
  float anchor_scale[MAX_YOLO_INPUT_NUM];
  int clip_box;
}__attribute__((packed)) tpu_kernel_api_yolov8NMS_t;


struct YoloV5Box {
  int x, y, width, height;
  float score;
  int class_id;
};

struct YoloV8Box {
    float x1, y1, x2, y2;
    // int x, y, width, height;
    float score;
    int class_id;
    std::string class_name;
    std::vector<float> mask;
    cv::Mat mask_img;  // 预测出来不仅有框，还有mask
    cv::Point left_center_point;  // 预测出来mask的左边界的中心点坐标
    cv::Point right_center_point; // 预测出来mask的右边界的中心点坐标
    float angle;
    float length;
    float width;
    std::vector<cv::Point> hullPoints;
};

template<typename T>
struct FrameInfo{
    FrameInfo(int channel,std::shared_ptr<T> img):channel_id(channel),image_ptr(img){}
    int channel_id;
    std::shared_ptr<T> image_ptr;
};


struct FrameInfoDetect{
    FrameInfoDetect(int channel,std::shared_ptr<bm_image> img):channel_id(channel),image_ptr(img),boxs_vec(){}
    int channel_id;
    std::shared_ptr<bm_image> image_ptr;
    std::vector<YoloV5Box> boxs_vec;
};

struct FrameInfoDetectYolov8Seg{
    FrameInfoDetectYolov8Seg(int channel, std::shared_ptr<bm_image> img):channel_id(channel), image_ptr(img), boxs_vec(), is_mask(false){}
    
    int channel_id;
    std::shared_ptr<bm_image> image_ptr;
    std::vector<YoloV8Box> boxs_vec;
    bool is_mask;  //获取mask数据

};

/**
 * @brief 根据源图像和目标图像的宽度和高度计算缩放比例，并根据宽高比确定是否对齐宽度
 *
 * 该函数计算源图像和目标图像的宽度和高度比例，并根据宽高比确定是否对齐宽度。
 * 如果目标图像的高度比例大于宽度比例，则对齐宽度，否则不对齐。
 *
 * @param src_w 源图像的宽度
 * @param src_h 源图像的高度
 * @param dst_w 目标图像的宽度
 * @param dst_h 目标图像的高度
 * @param alignWidth 指向一个布尔变量的指针，用于存储是否对齐宽度的结果
 *
 * @return 缩放比例
 */
inline float get_aspect_scaled_ratio(int src_w, int src_h, int dst_w, int dst_h, bool *alignWidth){
    float ratio;
    float r_w = (float)dst_w / src_w;
    float r_h = (float)dst_h / src_h;
    if (r_h > r_w) {
        *alignWidth = true;
        ratio = r_w;
    } else {
        *alignWidth = false;
        ratio = r_h;
    }
    return ratio;
}

#endif